package com.qinghe.pro.util.redis;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import com.qinghe.utils.common.SerializableUtil;

/**
 * redis 缓存基本数据
 * 
 * @author longfei
 */
@Component
public class CacheBasic {
	private static Logger logger = LoggerFactory.getLogger(CacheBasic.class);

	@Autowired
	private RedisTemplate<Serializable, Serializable> redisTemplate;

	/**
	 * 根据key缓存对象，不存在此key的缓存返回true；已存在的返回false
	 * 
	 * @param key
	 * @param object
	 * @param expire 秒
	 * 
	 * @return boolean
	 */
	public boolean setNx(final String key, final Object object, final Long expire) {
		logger.debug("add object to cache key:" + key);
		final byte[] bt = SerializableUtil.serialize(object);
		return (Boolean) redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
				boolean bl = connection.setNX(keyByte, bt);
				if (bl && expire > 0) {
					connection.expire(keyByte, expire);
				}
				return bl;
			}
		});
	}

	/**
	 * 缓存对象
	 * 
	 * @param key
	 * @param object
	 * @param expire 秒
	 * 
	 * @return boolean
	 */
	public boolean set(final String key, final Object object, final Long expire) {
		logger.debug("add object to cache key:" + key);
		final byte[] bt = SerializableUtil.serialize(object);
		redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
				connection.set(keyByte, bt);
				if (expire > 0) {
					connection.expire(keyByte, expire);
				}
				return null;
			}
		});
		return true;
	}

	/**
	 * 根据key从缓存读取对象
	 * 
	 * @param key
	 * 
	 * @return Object
	 */
	public Object get(final String key) {
		logger.debug("get object from cache key:" + key);
		Object obj = redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
				if (connection.exists(keyByte)) {
					byte[] value = connection.get(keyByte);
					Object obj = SerializableUtil.deSerialize(value);
					return obj;
				} else {
					return null;
				}
			}
		});
		return obj;
	}

	/**
	 * 根据key从缓存删除对象
	 * 
	 * @param key
	 */
	public void del(final String key) {
		logger.debug("del Object from cache key:" + key);
		redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
				if (connection.exists(keyByte)) {
					connection.del(keyByte);
				}
				return null;
			}
		});
	}

	/**
	 * 删除key开头的所有缓存
	 * 
	 * @param key
	 */
	public void delMany(final String key) {
		logger.debug("del list from cache key:" + key + "*");
		redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection)
					throws DataAccessException {
				byte[] keyByte = redisTemplate.getStringSerializer().serialize(key + "*");
				Set<byte[]> set = connection.keys(keyByte);
				for (byte[] bt : set) {
					if (connection.exists(bt)) {
						connection.del(bt);
					}
				}
				return null;
			}
		});
	}

	/**
	 * 缓存List<Object>
	 * 
	 * @param key
	 * @param list
	 * @param expire 秒
	 * 
	 * @return boolean
	 */
	public boolean setList(final String key, final List<Object> list, final Long expire) {
		logger.debug("add list to cache key:" + key);
		redisTemplate.execute(new RedisCallback<Object>() {
			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
				for (int i = 0; i < list.size(); i++) {
					connection.rPush(keyByte, SerializableUtil.serialize(list.get(i)));
				}
				if (expire > 0) {
					connection.expire(keyByte, expire);
				}
				return null;
			}
		});
		return true;
	}

	/**
	 * 从缓存读取List<Object>
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * 
	 * @return List<Object>
	 */
	public List<Object> getList(final String key, final int start, final int end) {
		logger.debug("get list from cache key:" + key + " start " + start + " end " + end);
		List<Object> obj = redisTemplate.execute(new RedisCallback<List<Object>>() {
			@Override
			public List<Object> doInRedis(RedisConnection connection) throws DataAccessException {
				byte[] keyByte = redisTemplate.getStringSerializer().serialize(key);
				if (connection.exists(keyByte)) {
					List<byte[]> byteArr = connection.lRange(keyByte, start, end);
					List<Object> list = new ArrayList<Object>();
					for (int i = 0; i < byteArr.size(); i++) {
						byte[] bt = byteArr.get(i);
						list.add(SerializableUtil.deSerialize(bt));
					}
					return list;
				} else {
					return null;
				}
			}
		});
		return obj;
	}

}
